home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 23 / AACD 23.iso / AACD / Online / opennap / level.c < prev    next >
C/C++ Source or Header  |  2001-06-08  |  6KB  |  244 lines

  1. /* Copyright (C) 2000-1 drscholl@users.sourceforge.net
  2.    This is free software distributed under the terms of the
  3.    GNU Public License.  See the file COPYING for details.
  4.  
  5.    $Id: level.c,v 1.54 2001/02/15 08:39:45 drscholl Exp $ */
  6.  
  7. #include <string.h>
  8. #include <stdlib.h>
  9. #include <stdio.h>
  10. #include <limits.h>
  11. #include <errno.h>
  12. #include "opennap.h"
  13. #include "debug.h"
  14.  
  15.  
  16. void
  17. logmode_change (char *sender, char *whom, int oldlevel, int newlevel)
  18. {
  19.     char    path[_POSIX_PATH_MAX];
  20.     FILE   *fp;
  21.  
  22.     if (!(Server_Flags & ON_LOGLEVEL_CHANGE))
  23.     return;
  24.     snprintf (path, sizeof (path), "%s/level.log", Config_Dir);
  25.     fp = fopen (path, "a");
  26.     if (!fp)
  27.     {
  28.     logerr ("level_log init", path);
  29.     return;
  30.     }
  31.     fprintf (fp, "%s Changed %s's level from %s(%d) to %s(%d)",
  32.          sender, whom,
  33.          oldlevel != -1 ? Levels[oldlevel] : "unknown", oldlevel,
  34.          Levels[newlevel], newlevel);
  35. #ifdef WIN32
  36.     fputs ("\r\n", fp);
  37. #else
  38.     fputc ('\n', fp);
  39. #endif
  40.     if (fflush (fp))
  41.     {
  42.     logerr ("level_log", "fflush");
  43.     fclose (fp);
  44.     return;
  45.     }
  46.     if (fclose (fp))
  47.     logerr ("level_log", "fclose");
  48. }
  49.  
  50. /* [ :<nick> ] <user> <level>
  51.    change the user level for a user */
  52. HANDLER (level)
  53. {
  54.     char   *sender_name, *av[2];
  55.     USER   *user, *sender;
  56.     int     level, ac = -1, curlevel = -1, desync = 0, savelevel = -1;
  57.     USERDB *db;
  58.  
  59.     (void) len;
  60.     ASSERT (validate_connection (con));
  61.  
  62.     if (pop_user_server (con, tag, &pkt, &sender_name, &sender))
  63.     return;
  64.  
  65.     if (pkt)
  66.     ac = split_line (av, FIELDS (av), pkt);
  67.     if (ac < 2)
  68.     {
  69.     log ("level: malformed request");
  70.     print_args (ac, av);
  71.     unparsable (con);
  72.     return;
  73.     }
  74.  
  75.     if ((level = get_level (av[1])) == -1)
  76.     {
  77.     if (ISUSER (con))
  78.         send_cmd (con, MSG_SERVER_NOSUCH,
  79.               "set user level failed: %s: invalid level", av[1]);
  80.     else
  81.     {
  82.         ASSERT (ISSERVER (con));
  83.         log ("level: invalid level %s from server %s", av[1], con->host);
  84.     }
  85.     return;
  86.     }
  87.  
  88.  
  89.     /* check to see if the user is registered (might be null) */
  90.     db = hash_lookup (User_Db, av[0]);
  91.  
  92.     /* check if the user is currently online (might be null) */
  93.     user = hash_lookup (Users, av[0]);
  94.  
  95.     /* make sure this is a valid nickname so we don't pass unchecked
  96.      * data across a server link.
  97.      */
  98.     if ((!db && !user) && invalid_nick (av[0]))
  99.     {
  100.     if (ISUSER (con))
  101.         send_cmd (con, MSG_SERVER_NOSUCH,
  102.               "set user level failed: invalid nickname");
  103.     else
  104.         log ("level: invalid nickname from server %s", con->host);
  105.     return;
  106.     }
  107.  
  108.     /* ensure that the user can execute this command */
  109.     if (sender && sender->level < LEVEL_ELITE)
  110.     {
  111.     /* a user is not allowed to set another user to a level greater
  112.      * or equal to their own.
  113.      */
  114.     if (level >= sender->level)
  115.     {
  116.         desync = 1;
  117.     }
  118.     /* check for permission to execute */
  119.     else if (db || user)
  120.     {
  121.         /* find the target's current user level */
  122.         curlevel = db ? db->level : user->level;
  123.  
  124.         /* we allow a user to set their own level lower, but not
  125.            a user with a level equal to or greater than their own. */
  126.         if (sender->level <= curlevel &&
  127.         (sender != user || curlevel < LEVEL_MODERATOR))
  128.         desync = 1;
  129.     }
  130.  
  131.     /* no permission */
  132.     if (desync)
  133.     {
  134.         if (ISUSER (con))
  135.         {
  136.         send_cmd (con, MSG_SERVER_NOSUCH,
  137.               "set user level failed: permission denied");
  138.         }
  139.         else
  140.         {
  141.         log ("level: %s is desynched", con->host);
  142.         log ("level: %s -> %s %s", sender->nick, av[0],
  143.              Levels[level]);
  144.         if (curlevel != -1)
  145.         {
  146.             /* reset the user's level on the remote site
  147.                to avoid desync.  we only do this when we know what the
  148.                real value should be since the userdb is not fully
  149.                synched when new servers are added. */
  150.             send_cmd (con, MSG_CLIENT_SETUSERLEVEL,
  151.                   ":%s %s %s", Server_Name, av[0],
  152.                   Levels[curlevel]);
  153.         }
  154.         }
  155.         return;
  156.     }
  157.     }
  158.  
  159.     /* if we get here, either we don't have enough info to verify
  160.      * whether the sender can execute and we're just going to pass it
  161.      * along, or it is registered here and ok to proceed.
  162.      */
  163.     if (!db)
  164.     {
  165.     /* if we have no db entry yet and the user is online we are in luck.
  166.        create a stub entry from the USER struct and continue.  otherwise
  167.        we don't do anything but pass this message along to our peer servers
  168.        since we don't have enough info to register. */
  169.     if (user)
  170.         db = create_db (user);
  171.     }
  172.  
  173.     if (db)
  174.     {
  175.     if (db->level == level)
  176.         return;        /* already set */
  177.  
  178.     savelevel = db->level;
  179.     db->level = level;
  180.  
  181.     /* if the user is online, we need to do some extra work */
  182.     if (user)
  183.     {
  184.         int     oldlevel = user->level;
  185.  
  186.         savelevel = oldlevel;
  187.         user->level = level;
  188.  
  189.         if (ISUSER (user->con))
  190.         {
  191.         char   *who;
  192.  
  193.         if (sender && sender->cloaked && level < LEVEL_MODERATOR)
  194.             who = "Operator";
  195.         else
  196.             who = sender_name;
  197.  
  198.         send_cmd (user->con, MSG_SERVER_NOSUCH,
  199.               "%s%s changed your user level to %s (%d)",
  200.               !sender ? "Server " : "", who, Levels[level],
  201.               level);
  202.  
  203.         if (level >= LEVEL_MODERATOR && oldlevel < LEVEL_MODERATOR)
  204.         {
  205.             LIST   *list;
  206.  
  207.             list = CALLOC (1, sizeof (LIST));
  208.             list->data = user->con;
  209.             Mods = list_push (Mods, list);
  210.         }
  211.         else if (level < LEVEL_MODERATOR
  212.              && oldlevel >= LEVEL_MODERATOR)
  213.         {
  214.             Mods = list_delete (Mods, user->con);
  215.         }
  216.         }
  217.  
  218.         /* non-mod+ users can't decloak so make sure they are
  219.            not cloaked */
  220.         if (user->level < LEVEL_MODERATOR && user->cloaked)
  221.         {
  222.         user->cloaked = 0;
  223.         notify_mods (CHANGELOG_MODE, "%s has decloaked", user->nick);
  224.         if (ISUSER (user->con))
  225.             send_cmd (user->con, MSG_SERVER_NOSUCH,
  226.                   "You are no longer cloaked.");
  227.         }
  228.     }
  229.     }
  230.  
  231.     pass_message_args (con, tag, ":%s %s %s", sender_name, av[0],
  232.                Levels[level]);
  233.  
  234.     /* if sender != NULL then it's not a server. and if savelevel == -1
  235.      * we're looking at a user that has already signed off, or is not known
  236.      */
  237.     if (sender && savelevel != -1)
  238.     logmode_change (sender_name, av[0], savelevel, level);
  239.  
  240.     notify_mods (LEVELLOG_MODE, "%s%s changed %s's user level to %s (%d)",
  241.          !sender ? "Server " : "",
  242.          sender_name, av[0], Levels[level], level);
  243. }
  244.